﻿using System;
using System.Collections.Generic;
using System.IO;
using System.Linq;
using System.Text;

namespace JcomTesters.Releases
{
    //复制树
    [jDesc("复制树",ok:true, args: new[] {
        "日志", "-log=;少用",
        "debug", "-debug",
        "覆盖", "-over=no -over=yes",
        "忽略文件", "-ig=f:xxx.txt",
        "忽略目录", "-ig=d:xxx",
        "忽略所有", "-ig=xxx",
        "[empty1]", "源目录 如 ab1",
        "[empty2]", "目标目录 如 ab2" })]
    class CpTreeCmd : Ab1Tester
    {

        //  cptree  ./
        //1.日志问题再处理一下，
        //2.写一个deltree 
        //public bool IsDebug { get; set; }

        debugInfo deb = new debugInfo();
        public override void Run(string[] args)
        {
            foreach (var item in args)
            {
                if (item.StartsWith("-log=")) { deb.log = item.Substring("-log=".Length); continue; }
                else if (item.StartsWith("-debug")) { isDebug = true; continue; }
                else if (item.StartsWith("-over=no")) { deb.over = "no_over"; continue; }
                else if (item.StartsWith("-over=yes")) { deb.over = "over"; continue; }
                else if (item.StartsWith("-over=ask")) { deb.over = "ask"; continue; }
                else if (item.StartsWith("-ig=f:") && item.Length > "-ig=f:".Length) { deb.ignoreF.Add(item.Substring("-ig=f:".Length)); continue; }
                else if (item.StartsWith("-ig=d:") && item.Length > "-ig=d:".Length) { deb.ignoreD.Add(item.Substring("-ig=d:".Length)); continue; }
                else if (item.StartsWith("-ig=") && item.Length > "-ig=".Length) { deb.ignoreAll.Add(item.Substring("-ig=".Length)); continue; }
                else if (item.StartsWith("-")) { continue; }
                //
                if (string.IsNullOrEmpty(deb.src)) deb.src = item;
                else deb.tar = item;
                continue;
            }

            if (string.IsNullOrEmpty(deb.src)) { Console.WriteLine("需要参数 src"); return; }
            if (string.IsNullOrEmpty(deb.tar)) { Console.WriteLine("需要参数 tar"); return; }
            if (string.IsNullOrEmpty(deb.over)) { deb.over = "over"; }//默认覆盖

            var p1 = Path.GetFullPath(deb.src);
            var p2 = Path.GetFullPath(deb.tar);
            jnlog = deb.log;

            //HttpJnlog.PostLog(jnlog, "", deb.isdebug);
            //HttpJnlog.PostLog(jnlog, "Start cptree", deb.isdebug);

            if (isDebug)
            {
                Console.WriteLine(" src to tar ");
                Console.WriteLine(" " + p1);
                Console.WriteLine(" exists: " + System.IO.Directory.Exists(p1));
                Console.WriteLine(" " + p2);
                Console.WriteLine(" over: " + deb.over);
            }
            else
            {
                //tree_copy_del(p1, p2, deb.over, deb.isdebug);
                cptreeV2(p1, p2, deb.over, isDebug);
            }
        }
        string jnlog = "";


        //src: 源绝对路径
        //tar: 目录绝对路径
        //opt: ask|over|no_over
        //换成广度遍历的
        private void cptreeV2(string src1, string tar1, string over_opt = "ask", bool isdebug = false)
        {
            var qList = new Queue<Tuple<string, string>>();
            qList.Enqueue(new Tuple<string, string>(src1, tar1));
            while (qList.Count != 0)
            {
                //var srcDir = dirList.Dequeue();
                var qItem = qList.Dequeue();
                var src = qItem.Item1;
                var tar = qItem.Item2;
                var files0 = Directory.GetFiles(src);


                if (!Directory.Exists(src))
                {
                    Console.WriteLine($" {src}目录不存在");
                    return;
                }

                if (!Directory.Exists(tar))
                {
                    if (isdebug)
                    {
                        Console.WriteLine($"创建了目录 {tar}");
                    }

                    if (!isdebug)
                    {
                        Directory.CreateDirectory(tar);
                    }
                }
                var len0 = (src).Length;


                foreach (var item2 in files0)
                {
                    var part0 = item2.Substring(len0);
                    if (part0.StartsWith("/") || part0.StartsWith("\\")) part0 = part0.Substring(1);
                    var tarp2 = Path.Combine(tar, part0);

                    if (deb.ignoreF.Where(t => item2.IndexOf(t) != -1).Any() || deb.ignoreAll.Where(t => item2.IndexOf(t) != -1).Any())
                    {
                        Console.WriteLine(" 忽略文件 " + item2);
                        //忽略
                        continue;
                    }
                    var canCopy = true;
                    if (File.Exists(tarp2) && over_opt == "ask")//是否需要询问
                    {
                        Console.WriteLine($" 已存在文件 {tarp2} 是否覆盖");
                        Console.Write($" (直接回车)否 (y)是 (a)都是 (n)都否:");
                        var reads = Console.ReadLine().ToLower();

                        if (reads == "a") { over_opt = "over"; }
                        else if (reads == "n") { over_opt = "no_over"; }
                        else if (reads != "y") { canCopy = false; }
                    }
                    if (over_opt == "over") canCopy = true;
                    else if (File.Exists(tarp2) && over_opt == "no_over") canCopy = false;

                    if (canCopy)
                    {
                        //HttpJnlog.PostLog(jnlog, $" 复制了 {item2} => {tarp2}", isdebug);
                        Console.WriteLine($" 复制了 {item2} => {tarp2}");
                        if (!isdebug)
                        {
                            File.Copy(item2, tarp2, true);
                        }
                    }
                    else
                    {
                        //HttpJnlog.PostLog(jnlog, $" 忽略了 {item2}", isdebug);
                        Console.WriteLine($" 忽略了 {item2}");
                    }
                }


                var dirs = Directory.GetDirectories(src);
                foreach (var item in dirs)
                {
                    if (deb.ignoreD.Where(t => item.IndexOf(t) != -1).Any() || deb.ignoreAll.Where(t => item.IndexOf(t) != -1).Any())
                    {
                        Console.WriteLine($" 忽略目录 {item}");
                        //忽略
                        continue;
                    }
                    //if(item.IndexOf())

                    var part0 = item.Substring(len0);
                    if (part0.StartsWith("/") || part0.StartsWith("\\")) part0 = part0.Substring(1);
                    ////Console.WriteLine(part0);
                    //Console.WriteLine(Path.Combine(tar,item.Substring(len0)));
                    //Console.WriteLine(Path.Combine( tar,part0));
                    var nTarDir = Path.Combine(tar, part0);
                    //if (!Directory.Exists(nTarDir)) Directory.CreateDirectory(nTarDir);
                    //tree_copy()
                    //Console.WriteLine(item);
                    //Console.WriteLine(nTarDir);

                    //tree_copy(item, nTarDir, over_opt, isdebug);
                    qList.Enqueue(new Tuple<string, string>(item, nTarDir));
                }
            }
        }


        //两个绝对路径转相对路径
        string RelativePath(string absolutePath, string relativeTo)
        {
            string[] absoluteDirectories = absolutePath.Split('\\');
            string[] relativeDirectories = relativeTo.Split('\\');

            //Get the shortest of the two paths
            int length = absoluteDirectories.Length < relativeDirectories.Length ? absoluteDirectories.Length : relativeDirectories.Length;

            //Use to determine where in the loop we exited
            int lastCommonRoot = -1;
            int index;

            //Find common root
            for (index = 0; index < length; index++)
                if (absoluteDirectories[index] == relativeDirectories[index])
                    lastCommonRoot = index;
                else
                    break;

            //If we didn't find a common prefix then throw
            if (lastCommonRoot == -1)
                throw new ArgumentException("Paths do not have a common base");

            //Build up the relative path
            StringBuilder relativePath = new StringBuilder();

            //Add on the ..
            for (index = lastCommonRoot + 1; index < absoluteDirectories.Length; index++)
                if (absoluteDirectories[index].Length > 0)
                    relativePath.Append("..\\");

            //Add on the folders
            for (index = lastCommonRoot + 1; index < relativeDirectories.Length - 1; index++)
                relativePath.Append(relativeDirectories[index] + "\\");
            relativePath.Append(relativeDirectories[relativeDirectories.Length - 1]);

            return relativePath.ToString();
        }
        class debugInfo
        {
            public string src { get; set; }
            public string tar { get; set; }
            public string log { get; set; }
            public string over { get; set; }//默认覆盖
                                            //public bool is_ask { get; set; }
            public List<string> ignoreF { get; set; } = new List<string>();//忽略文件
            public List<string> ignoreD { get; set; } = new List<string>();//忽略目录
            public List<string> ignoreAll { get; set; } = new List<string>();//忽略所有(文件或目录)
        }
    }

}